# -*- coding: UTF-8 -*-
# __author__ = '10459'
from flask_sqlalchemy import SQLAlchemy as _SQLAlchemy, BaseQuery
from sqlalchemy import SmallInteger, Column, Integer
from contextlib import contextmanager
from datetime import datetime


class SQLAlchemy(_SQLAlchemy):
    @contextmanager
    def auto_commit(self):
        try:
            yield
            self.session.commit()
        except Exception as e:
            db.session.rollback()
            raise e


# 改写框架内部函数覆盖的时候，这个时候定义了一个类，改写了basequery里的filter_by方法，但是没有覆盖
class Query(BaseQuery):
    def filter_by(self, **kwargs):
        if 'status' not in kwargs.keys():
            kwargs['status'] = 1
        return super(Query, self).filter_by(**kwargs)


# 覆盖框架的函数，调用原来框架不受影响，要传入参数query_class为新的类，才会替换框架的类
db = SQLAlchemy(query_class=Query)


class Base(db.Model):
    __abstract__ = True  # 没有主键，所以要加这行代码
    create_time = Column("create_time", Integer)  # 时间戳不要在这里创建不能用default，类变量与实例变量的区别
    status = Column(SmallInteger, default=1)  # 1为没有删除，否则相当于删除的，filter_by中需要包含这个，那样写麻烦，可以封装

    def __init__(self):
        self.create_time = int(datetime.now().timestamp())  # 实例化的时候转换成时间戳，这个要插入另外一条数据才会有

    # 利用python动态语言的特性
    def set_attrs(self, attrs_dict):
        for key, value in attrs_dict.items():
            if hasattr(self, key) and key != "id":  # 查看是否含有key
                setattr(self, key, value)  # 赋值

    @property
    def create_datetime(self):
        if self.create_time:
            return datetime.fromtimestamp(self.create_time)
        else:
            return None

    def delete(self):
        self.status = 0
